// GalaxyScreenPresentationModel.cs
//
// Copyright (c) 2009 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;

using Supremacy.Annotations;
using Supremacy.Orbitals;
using Supremacy.Universe;

namespace Supremacy.Client.Views
{
    public class GalaxyScreenPresentationModel : PresentationModelBase
    {
        #region Fields
        private IEnumerable<Ship> _availableShips;
        private GalaxyScreenInputMode _inputMode;
        private GalaxyScreenOverviewMode _overviewMode;
        private Sector _selectedSector;
        private Sector _hoveredSector;
        private string _selectedSectorAllegiance;
        private string _selectedSectorInhabitants;
        private Ship _selectedShip;
        private ShipView _selectedShipInTaskForce;
        private IEnumerable<ShipView> _selectedShipsInTaskForce;
        private Ship _selectedShipResolved;
        private FleetView _selectedTaskForce;
        private TradeRoute _selectedTradeRoute;
        private IEnumerable<FleetView> _taskForces;
        private IEnumerable<TradeRoute> _tradeRoutes;
        private readonly EmpirePlayerStatusCollection _empirePlayers;
        #endregion

        #region Events
        public event EventHandler AvailableShipsChanged;
        public event EventHandler InputModeChanged;
        public event EventHandler OverviewModeChanged;
        public event EventHandler SelectedSectorAllegianceChanged;
        public event EventHandler SelectedSectorChanged;
        public event EventHandler HoveredSectorChanged;
        public event EventHandler SelectedSectorInhabitantsChanged;
        public event EventHandler SelectedShipChanged;
        public event EventHandler SelectedShipInTaskForceChanged;
        public event EventHandler SelectedShipsInTaskForceChanged;
        public event EventHandler SelectedTaskForceChanged;
        public event EventHandler TaskForcesChanged;
        public event EventHandler SelectedTradeRouteChanged;
        public event EventHandler TradeRoutesChanged;
        #endregion

        #region Constructors and Finalizers
        public GalaxyScreenPresentationModel([NotNull] IClientContext clientContext)
            : base(clientContext)
        {
            _empirePlayers = new EmpirePlayerStatusCollection();
            
            _empirePlayers.AddRange(
                from civ in clientContext.CurrentGame.Civilizations
                where civ.IsEmpire
                select new EmpirePlayerStatus(clientContext, civ)
                       {
                           Player = clientContext.Players.FirstOrDefault(o => o.EmpireID == civ.CivID)
                       }
                );
        }
        #endregion

        #region Properties and Indexers
        public IEmpirePlayerStatusCollection EmpirePlayers
        {
            get { return _empirePlayers; }
        }

        public IEnumerable<Ship> AvailableShips
        {
            get { return _availableShips; }
            set
            {
                if (Equals(_availableShips, value))
                    return;
                _availableShips = value;
                OnAvailableShipsChanged();
            }
        }

        public GalaxyScreenInputMode InputMode
        {
            get { return _inputMode; }
            set
            {
                if (Equals(_inputMode, value))
                    return;
                _inputMode = value;
                OnInputModeChanged();
            }
        }

        public GalaxyScreenOverviewMode OverviewMode
        {
            get { return _overviewMode; }
            set
            {
                if (Equals(_overviewMode, value))
                    return;
                _overviewMode = value;
                OnOverviewModeChanged();
            }
        }

        public Sector SelectedSector
        {
            get { return _selectedSector; }
            set
            {
                if (Equals(_selectedSector, value))
                    return;
                _selectedSector = value;
                OnSelectedSectorChanged();
            }
        }

        public Sector HoveredSector
        {
            get { return _hoveredSector; }
            set
            {
                if (Equals(_hoveredSector, value))
                    return;
                _hoveredSector = value;
                OnHoveredSectorChanged();
            }
        }

        internal Sector SelectedSectorInternal
        {
            get { return _selectedSector; }
            set
            {
                _selectedSector = value;
                OnSelectedSectorChanged();
            }
        }

        public string SelectedSectorAllegiance
        {
            get { return _selectedSectorAllegiance; }
            set
            {
                if (Equals(_selectedSectorAllegiance, value))
                    return;
                _selectedSectorAllegiance = value;
                OnSelectedSectorAllegianceChanged();
            }
        }

        public string SelectedSectorInhabitants
        {
            get { return _selectedSectorInhabitants; }
            set
            {
                if (Equals(_selectedSectorInhabitants, value))
                    return;
                _selectedSectorInhabitants = value;
                OnSelectedSectorInhabitantsChanged();
            }
        }

        public Ship SelectedShip
        {
            get { return _selectedShipResolved ?? _selectedShip; }
            set
            {
                if (Equals(_selectedShip, value) &&Equals(_selectedShipResolved, value))
                    return;
                _selectedShip = value;
                _selectedShipResolved = value;
                OnSelectedShipChanged();
            }
        }

        public ShipView SelectedShipInTaskForce
        {
            get { return _selectedShipInTaskForce; }
            set
            {
                if (Equals(_selectedShipInTaskForce, value))
                    return;

                _selectedShipInTaskForce = value;
                OnSelectedShipInTaskForceChanged();

                if ((_selectedShipInTaskForce == null) || !_selectedShipInTaskForce.IsOwned)
                    return;

                _selectedShipResolved = _selectedShipInTaskForce.Source;
                OnSelectedShipChanged();
            }
        }

        public IEnumerable<ShipView> SelectedShipsInTaskForce
        {
            get
            {
                return _selectedShipsInTaskForce ??
                       Enumerable.Empty<ShipView>();
            }
            set
            {
                if (Equals(_selectedShipInTaskForce, value))
                    return;

                _selectedShipsInTaskForce = value;
                OnSelectedShipsInTaskForceChanged();
            }
        }

        public FleetView SelectedTaskForce
        {
            get { return _selectedTaskForce; }
            set
            {
                if (Equals(_selectedTaskForce, value))
                    return;
                _selectedTaskForce = value;
                OnSelectedTaskForceChanged();
            }
        }

        public TradeRoute SelectedTradeRoute
        {
            get { return _selectedTradeRoute; }
            set
            {
                if (Equals(_selectedTradeRoute, value))
                    return;
                _selectedTradeRoute = value;
                OnSelectedTradeRouteChanged();
            }
        }

        public IEnumerable<FleetView> TaskForces
        {
            get { return _taskForces; }
            set
            {
                if (Equals(_taskForces, value))
                    return;
                _taskForces = value;
                OnTaskForcesChanged();
            }
        }

        public IEnumerable<TradeRoute> TradeRoutes
        {
            get { return _tradeRoutes; }
            set
            {
                if (Equals(_tradeRoutes, value))
                    return;
                _tradeRoutes = value;
                OnTradeRoutesChanged();
            }
        }
        #endregion

        #region Private Methods
        private void OnAvailableShipsChanged()
        {
            var handler = this.AvailableShipsChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnInputModeChanged()
        {
            var handler = this.InputModeChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnOverviewModeChanged()
        {
            var handler = this.OverviewModeChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedSectorAllegianceChanged()
        {
            var handler = this.SelectedSectorAllegianceChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedSectorChanged()
        {
            var handler = this.SelectedSectorChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnHoveredSectorChanged()
        {
            var handler = this.HoveredSectorChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedSectorInhabitantsChanged()
        {
            var handler = this.SelectedSectorInhabitantsChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedShipChanged()
        {
            var handler = this.SelectedShipChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedShipInTaskForceChanged()
        {
            var handler = this.SelectedShipInTaskForceChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedShipsInTaskForceChanged()
        {
            var handler = this.SelectedShipsInTaskForceChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedTaskForceChanged()
        {
            var handler = this.SelectedTaskForceChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnSelectedTradeRouteChanged()
        {
            var handler = this.SelectedTradeRouteChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnTaskForcesChanged()
        {
            var handler = this.TaskForcesChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        private void OnTradeRoutesChanged()
        {
            var handler = this.TradeRoutesChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
        #endregion
    }
}